'use strict'

import { app, protocol, BrowserWindow, ipcMain, BrowserView } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: 'app', privileges: { secure: true, standard: true } }
])

const path = require('path')
let mainWin;
async function createWindow() {
  // Create the browser window.
  mainWin = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {

      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      contextIsolation: false,
      nodeIntegration: true,
      preload: path.join(__dirname, 'preload.js'),
      nativeWindowOpen: true,
      nodeIntegrationInWorker: true, // 多线程
      webSecurity: false,
    }
  })

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await mainWin.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) mainWin.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    mainWin.loadURL('app://./index.html')
  }
}

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      console.error('Vue Devtools failed to install:', e.toString())
    }
  }
  createWindow()

  startServer(
    '0.0.0.0', 5688,
    {
      useHttps: false, httpsCert: '', httpsCertKey: ''
    }
  )
  console.log('已经启动服务器: ', 5688)
})


// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', (data) => {
      if (data === 'graceful-exit') {
        app.quit()
      }
    })
  } else {
    process.on('SIGTERM', () => {
      app.quit()
    })
  }
}

// 监听获取打印机列表的指令
ipcMain.on('getPrinters', (event) => {
  const lists = mainWin.webContents.getPrintersAsync()

  lists.then(res => {
    mainWin.webContents.send('getPrinters', res)
  })

})

// 防止打印重复
let printLists = {}

ipcMain.on('toPrint', (event, args) => {
  console.log('收到打印数据: ', args._id)

  if (printLists[args._id]) {
    console.log('该任务已经运行了')
    return
  }
  printLists[args._id] = Math.round((new Date()) / 1000)
  if (JSON.stringify(printLists) !== '{}') {
    const currentTime = Math.round((new Date()) / 1000)
    const te = 7200
    for (const printListsKey in printLists) {
      if (currentTime - printLists[printListsKey] > te) {
        delete printLists[printListsKey]
      }
    }
  }

  let dataInfo = null
  try {
    dataInfo = JSON.parse(args.msg)
    console.log(dataInfo)
    console.log(args._id)
  } catch (e) {
    console.log('解码报错: ', e)
    const ret = { code: 101, msg: '解码错误', data: dataInfo, info: {}}
    mainWin.webContents.send('printRet', ret)
    ret.args = args
    mainWin.webContents.send('printNotice', ret)
    return
  }
  // 获取打印机列表
  mainWin.webContents.getPrintersAsync().then(res => {
    const len = res.length ? res.length : 0
    if (!len) {
      const ret = { code: 101, msg: '打印机列表为空', data: dataInfo, info: {}}
      mainWin.webContents.send('printRet', ret)

      ret.args = args
      mainWin.webContents.send('printNotice', ret)
      return
    }

    const msgs = {
      0: "空闲状态", 1: "打印队列已暂停", 2: "由于错误情况，打印机无法打印",
      4: "打印队列正在删除打印作业", 8: "打印机卡纸",16: "打印机中没有或已用完当前打印作业所需的纸张类型",
      32: "打印机正在等待用户将打印介质放入手动送纸盒",64: "打印机中的纸张导致未指定的错误情况",128: "打印机处于脱机状态",
      256: "打印机正在与打印服务器交换数据",512: "打印机正忙", 1024: "设备正在打印", 2048: "打印机的输出纸盒已满",
      4096: "状态信息不可用",8192: "打印机正在等待打印作业", 16384: "设备正在执行某种工作，如果此设备是集打印机、传真机和扫描仪于一体的多功能设备，则不需要打印",
      32768: "打印机正在初始化",65536: "打印机正在预热",131072: "打印机中只剩下少量墨粉",262144: "打印机墨粉用完", 524288: "打印机不能打印当前页",
      1048576: "打印机要求通过用户操作来更正错误情况", 2097152: "打印机无可用内存", 4194304: "打印机上的门已打开", 8388608: "打印机处于错误状态",
      16777216: "打印机处于节能模式",
    }

    let exist = false

    for (let i = 0; i < len; i++) {
      if (res[i].name === dataInfo.printer) {
        exist = true

        res[i].status_text = msgs[res[i].status] ? msgs[res[i].status] : '未知'

        if (res[i].status !== 0) {
          const ret = { code: 101, msg: '打印失败', data: dataInfo, info: res[i]}
          mainWin.webContents.send('printRet', ret)
          ret.args = args
          mainWin.webContents.send('printNotice', ret)
          break
        }

        // 开始调用打印机打印
        // 创建窗口对象
        const view = new BrowserView({
          webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
            nodeIntegrationInWorker: true,
            enableRemoteModule: true,
            devTools: true,
          }
        })

        mainWin.addBrowserView(view)
        console.log('路径: ', 'file://', __dirname, './sections/print/print1.html')
        console.log('路径: ', path.join(__dirname, '/../public/printImg.html'))
        if (dataInfo.type === 'img') {
          if (process.env.WEBPACK_DEV_SERVER_URL) {
            view.webContents.loadURL(path.join(__dirname, '/../public/printImg.html'))
          } else {
            // Load the index.html when not in development
            view.webContents.loadURL('app://./printImg.html')
          }
        }
        if (dataInfo.type === 'html') {

          if (process.env.WEBPACK_DEV_SERVER_URL) {
            view.webContents.loadURL(path.join(__dirname, '/../public/printhtml.html'))
          } else {
            // Load the index.html when not in development
            view.webContents.loadURL('app://./printhtml.html')
          }
        }
        view.setBounds({ x: -1000, y: -1000, width: 180, height: 160 });
        view.webContents.once("dom-ready", () => {
          console.log('加载完毕')
          view.webContents.send('webview-print-render', dataInfo)
        })
        console.log('订阅ipc')
        view.webContents.on("ipc-message", (event, channel) => { // 调用打印方法
          console.log('收到打印的消息')
          view.webContents.print({
            silent: true,
            printBackground: false,
            deviceName: args.printer, // 打印机对象的name
          }, data => {				// 打印成功后，移除BrowserView
            console.log('打印结果: ', data)
            const ret = {
              code: data ? 200 : 101,
              msg: data ? '打印成功' : '打印失败',
              data: dataInfo,
              info: res[i]
            }
            mainWin.webContents.send('printRet', ret)
            ret.args = args
            mainWin.webContents.send('printNotice', ret)
            mainWin.removeBrowserView(view);
          })
        })
        break
      }

    }
    if (!exist) {
      const ret = { code: 101, msg: '不存在该打印机', data: dataInfo, info: {}}
      mainWin.webContents.send('printRet', ret)
      ret.args = args
      mainWin.webContents.send('printNotice', ret)
    }
  })
})

// ===================================================
// ================= 创建http服务器 ====================
import express from 'express'
import bodyParser from 'body-parser';
const expressApp = express()
let appSrv;

const sockets = new Set();

let webContents;

// 去掉跨域
expressApp.use(function (req, resp, next) {
  resp.set('Access-Control-Allow-Origin', '*');
  resp.set('Access-Control-Allow-Headers', ['Content-Type',].join(','));
  next();
})

expressApp.use(bodyParser.json({limit: '200mb'}));
expressApp.use(bodyParser.urlencoded({limit: '200mb', extended: true}));

// 解决跨域问题
expressApp.all("*",function(req,res,next){
  // 设置允许跨域的域名,*代表允许任意域名跨域
  res.header('Access-Control-Allow-Origin','*');
  // 允许的header类型
  res.header('Access-Control-Allow-Headers','content-type');
  // 跨域允许的请求方式
  res.header('Access-Control-Allow-Methods','DELETE,PUT,POST,GET,OPTIONS');
  if(req.method.toLowerCase() == 'options')
    res.send(200); // 让options 尝试请求快速结束
  else
    next();
})

expressApp.get('/', (req, res) => {
  res.json({ code: 200, msg: '访问成功', data: []});
});

expressApp.get('/getPrinterLists', (req, res) => {

  res.json({ code: 200, data: mainWin.webContents.getPrinters(), msg: '获取成功' })
})

expressApp.post('/print', (req, res) => {
  console.log('req', req.params)
  console.log('req', req.path)
  console.log('req', req.body)
  console.log('======================================')

  const body = req.body

  if (JSON.stringify(body) !== '{}' && body.length) {
    const addData = []
    for (let i = 0; i < body.length; i++) {
      addData.push({
        status: 0,
        id: body[i].id ? body[i].id : 0,
        msg: JSON.stringify(body[i]),
        create_time: Math.round((new Date() / 1000)),
        start_time: 0,
        print_time: 0,
        user_id: 1,
        print_result: ''
      })
    }
    mainWin.webContents.send('addPrint', addData)
    res.json({ code: 200, msg: '提交成功', data: addData});
    return
  }
  res.json({ code: 101, msg: '缺少参数', data: []});
});

import * as https from "https";
function startServer(hostname, port, { useHttps, httpsCert, httpsCertKey }) {

  return new Promise(resolve => {
    if (useHttps) {
      appSrv = https.createServer({
        cert: httpsCert,
        key : httpsCertKey,
      }, expressApp).listen(port, hostname, listenHandler);
    } else {
      appSrv = expressApp.listen(port, hostname, listenHandler);
    }

    appSrv.on('connection', socket => {
      sockets.add(socket);
      console.log('收到一个连接')
      socket.on('close', () => {
        sockets.delete(socket);
      })
    });

    function listenHandler() {
      const addr = appSrv.address();
      console.log('addr: ', addr)
      resolve();
    }
  });
}


function quit() {
  if (appSrv) {
    sockets.forEach(socket => {
      socket.destroy();
    });
    appSrv.close(() => {
      app.quit();
    });
  } else {
    app.quit();
  }

}

